package com.citywithincity.redis.utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.citywithincity.utils.ConfigReader;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Response;
import redis.clients.jedis.Tuple;

public class RedisUtil {
	private static JedisPool jedisPool;

	private static void create() {
		if (jedisPool != null) {
			jedisPool.close();
		}
		String server = ConfigReader.getDefault().get("redis_server");
		int port = ConfigReader.getDefault().getInt("redis_port");
		JedisPoolConfig config = new JedisPoolConfig();
		config.setMaxWaitMillis(1000);
		config.setMaxIdle(1000);
		config.setMaxTotal(1000);
		jedisPool = new JedisPool(config, server, port);
	}

	public static void removePattern(byte[] prefix) {
		Jedis jedis = null;
		Pipeline pipeline = null;
		try {
			jedis = getResource();
			pipeline = pipline();
			Set<byte[]> keys = jedis.keys(prefix);
			pipeline.multi();
			for (byte[] bs : keys) {
				pipeline.del(bs);
			}
			pipeline.exec();

		} finally {
			if (jedis != null) {
				jedis.close();
			}
			if (pipeline != null) {
				try {
					pipeline.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	static {
		create();
		/*
		 * ConfigReader reader = ConfigReader.getDefault();
		 * 
		 * // 创建jedis池配置实例
		 * 
		 * 
		 * // 设置池配置项值 String maxTotal = reader.get("redis.pool.maxTotal", "4");
		 * config.setMaxTotal(Integer.parseInt(maxTotal));
		 * 
		 * String maxIdle = reader.get("redis.pool.maxIdle", "4");
		 * config.setMaxIdle(Integer.parseInt(maxIdle));
		 * 
		 * String minIdle = reader.get("redis.pool.minIdle", "1");
		 * config.setMinIdle(Integer.parseInt(minIdle));
		 * 
		 * String maxWaitMillis = reader.get("redis.pool.maxWaitMillis",
		 * "1024"); config.setMaxWaitMillis(Long.parseLong(maxWaitMillis));
		 * 
		 * String testOnBorrow = reader.get("redis.pool.testOnBorrow", "true");
		 * config.setTestOnBorrow("true".equals(testOnBorrow));
		 * 
		 * String testOnReturn = reader.get("redis.pool.testOnReturn", "true");
		 * config.setTestOnReturn("true".equals(testOnReturn));
		 * 
		 * String server = reader.get("redis.server");
		 * if(StringUtils.isEmpty(server)){ throw new IllegalArgumentException(
		 * "JedisPool redis.server is empty!"); }
		 * 
		 * String[] host_arr = server.split(","); if(host_arr.length>1){ throw
		 * new IllegalArgumentException("JedisPool redis.server length > 1"); }
		 * 
		 * String[] arr = host_arr[0].split(":");
		 * 
		 * 
		 * jedisPool = new JedisPool(config, arr[0], Integer.parseInt(arr[1]));
		 */

	}

	public static List<Tuple> toListWithScores(Collection<Tuple> set) {
		List<Tuple> list = new ArrayList<Tuple>(set.size());
		for (Tuple bs : set) {
			list.add(bs);
		}
		return list;
	}

	public static List<String> toList(Collection<byte[]> set) {
		List<String> list = new ArrayList<String>(set.size());
		for (byte[] bs : set) {
			list.add(new String(bs));
		}
		return list;
	}

	/**
	 * 这个是用来读取的
	 * 
	 * @return
	 */
	public static Jedis read() {
		Jedis jedis = getResource();
		return jedis;
	}

	public static Jedis getResource() {
		synchronized (RedisUtil.class) {
			try {
				Jedis jedis = jedisPool.getResource();
				jedis.auth("123");
				return jedis;
			} catch (Throwable t) {
				t.printStackTrace();
				create();
				Jedis jedis = jedisPool.getResource();
				jedis.auth("123");
				return jedis;
			}
		}

	}

	public static Jedis write() {
		Jedis jedis = getResource();
		return jedis;
	}

	public static Pipeline pipline() {
		Jedis jedis = getResource();
		return jedis.pipelined();
	}

	public static String getKey(String keyName, Object id) {
		return new StringBuilder(keyName).append(':').append(id).toString();
	}

	public static String hget(Jedis jedis, String key, String subKey) {
		if (subKey.length() > 3) {
			int part = 3;
			String part1 = subKey.substring(0, part);
			String part2 = subKey.substring(part);
			return jedis.hget(RedisUtil.getKey(key, part1), part2);
		} else {
			return jedis.hget(key, subKey);
		}
	}

	public static Set<String> convert(Collection<byte[]> set) {
		Set<String> reSet = new HashSet<String>();
		for (byte[] bs : set) {
			reSet.add(new String(bs));
		}
		return reSet;
	}

	public static void close(Jedis jedis) {
		if (jedis != null) {
			try {
				jedis.close();
			} catch (Throwable e) {
			}
		}
	}

	public static void close(Pipeline jedis) {
		if (jedis != null) {
			try {
				jedis.close();
			} catch (IOException e) {
			}
		}
	}

	public static interface IPiplineAction {

		void execute(Pipeline jedis);

	}
	
	public static interface IJedisAction {

		void execute(Jedis jedis);

	}

	public static interface IJedisSetGetter {

		Set<String> execute(Jedis jedis);

	}
	
	public static interface IJedisExecutor<R> {

		R execute(Jedis jedis);

	}
	
	
	public static  List<String> getList(Set<String> set){
		List<Response<String>> list = new ArrayList<Response<String>>(set.size());
		List<String> result = new ArrayList<String>(set.size());
		Pipeline jedis = null;
		try {
			jedis = RedisUtil.pipline();

			jedis.multi();
			
			for (String t : set) {
				Response<String> response = jedis.get(t);
				list.add(response);
			}
			jedis.exec();
			
		} finally {
			RedisUtil.close(jedis);
		}
		

		for (Response<String> response : list) {
			result.add(response.get());
		}
		

		return result;
	}

	public static void execMutil(IPiplineAction action) {
		Pipeline jedis = null;
		try {
			jedis = RedisUtil.pipline();

			jedis.multi();

			action.execute(jedis);

			jedis.exec();

		} finally {
			RedisUtil.close(jedis);
		}
	}

	public static void exec(IJedisAction action) {
		Jedis jedis = null;
		try {
			jedis = RedisUtil.getResource();
			action.execute(jedis);
		} finally {
			RedisUtil.close(jedis);
		}
	}
	
	public static <R> R execute(IJedisExecutor<R> action) {
		Jedis jedis = null;
		try {
			jedis = RedisUtil.getResource();
			return action.execute(jedis);
		} finally {
			RedisUtil.close(jedis);
		}
	}

	public static Set<String> getSet(IJedisSetGetter action) {
		Jedis jedis = null;
		try {
			jedis = RedisUtil.getResource();
			return action.execute(jedis);
		} finally {
			RedisUtil.close(jedis);
		}
	}
}
